package com.sikaryofficial.backend.manager;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sikaryofficial.backend.constant.MyStatisticsTypeEnum;
import com.sikaryofficial.backend.domain.dto.req.EvaluateReplyListReq;
import com.sikaryofficial.backend.domain.dto.req.EvaluateReplyReq;
import com.sikaryofficial.backend.domain.dto.resp.BrandTasteEvaluateDTO;
import com.sikaryofficial.backend.domain.dto.resp.EvaluateReplyDTO;
import com.sikaryofficial.backend.domain.entity.BrandTasteEvaluate;
import com.sikaryofficial.backend.domain.mapping.BrandTasteEvaluateMapping;
import com.sikaryofficial.backend.domain.vo.ObjectCount;
import com.sikaryofficial.backend.service.IAttachmentService;
import com.sikaryofficial.backend.service.IBrandTasteEvaluateReplyService;
import com.sikaryofficial.backend.service.IBrandTasteEvaluateService;
import com.sikaryofficial.backend.service.IMyStatisticsService;
import com.sikaryofficial.backend.service.statistics.MyStatisticsProcessor;
import com.sikaryofficial.backend.service.statistics.MyStatisticsEvent;
import com.sikaryofficial.backend.service.user.UserCacheService;
import com.sikaryofficial.backend.service.useraction.cache.UserActionCacheService;
import com.sikaryofficial.common.core.exception.ServiceException;
import com.sikaryofficial.common.security.utils.SecurityUtils;
import com.sikaryofficial.system.api.model.att.AttachmentResp;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author : qinjinyuan
 * @desc : 商店分享管理服务
 * @date : 2023/10/30 15:39
 */
@Service
@Slf4j
@SuppressWarnings(value="unchecked")
public class EvaluateReplyManager {

    @Autowired
    private IBrandTasteEvaluateReplyService replyService;
    @Autowired
    private IBrandTasteEvaluateService evaluateService;
    @Autowired
    private MyStatisticsProcessor myListener;
    @Autowired
    private IAttachmentService attachmentService;
    @Autowired
    private IMyStatisticsService myStatisticsService;
    @Autowired
    private UserCacheService userCacheService;
    @Autowired
    private UserActionCacheService userActionCacheService;

    @Transactional(rollbackFor = Exception.class)
    public EvaluateReplyDTO saveReply(EvaluateReplyReq evaluateReplyReq) {
        Long userId = SecurityUtils.getUserId();
        // 判定评价ID是否存在
        BrandTasteEvaluate brandTasteEvaluate = evaluateService.getOne(new LambdaQueryWrapper<BrandTasteEvaluate>()
                .eq(BrandTasteEvaluate::getEvaluateId, evaluateReplyReq.getEvaluateId())
                .eq(BrandTasteEvaluate::getDeletedVersion, 0L)
                .last(" limit 1 ")
        );
        if (Objects.isNull(brandTasteEvaluate)) {
            throw new ServiceException("the evaluate id invalid.");
        }
        EvaluateReplyDTO result = replyService.saveReply(evaluateReplyReq);
        if (Objects.nonNull(result)) {
            // 填充头像数据
            result.setAvatar(userCacheService.getSignUserAvatar(result.getCreatedBy()));
            // 填充昵称
            result.setNickName(userCacheService.getSignUserNickName(result.getCreatedBy()));
        }
        // 4.1 添加我的评论回复 （跟评）统计数量
        myListener.addMyStatistics(new MyStatisticsEvent(MyStatisticsTypeEnum.COMMENTS_REPLAY_NUM.getBusinessType(), userId, evaluateReplyReq.getEvaluateReplyId()));
        // 4.2 添加评论回复总数
        myListener.addMyStatistics(new MyStatisticsEvent(MyStatisticsTypeEnum.COMMENTS_EVALUATE_REPLAY_NUM.getBusinessType(), userId, evaluateReplyReq.getEvaluateId()));
        return result;
    }

    public IPage<EvaluateReplyDTO> list(EvaluateReplyListReq req) {
        if (Objects.nonNull(req.getEvaluateId()) && req.getEvaluateId() <= 0) {
            return new Page<>(req.getPageNum(), req.getPageSize(), 0);
        }
        if (Objects.nonNull(req.getUserId()) && req.getUserId() <= 0) {
            return new Page<>(req.getPageNum(), req.getPageSize(), 0);
        }
        Page<EvaluateReplyDTO> customerPage = new Page<>(req.getPageNum(), req.getPageSize());
        IPage<EvaluateReplyDTO> evaluateDTOIPage = replyService.replyList(customerPage, req);
        List<EvaluateReplyDTO> evaluateReplyDTOList = evaluateDTOIPage.getRecords();
        if (CollUtil.isEmpty(evaluateReplyDTOList)) {
            return new Page<>(req.getPageNum(), req.getPageSize(), 0);
        }
        // 填充头像数据
        Map<Long, String> userAvatarMap = userCacheService.getMultiUserAvatar(evaluateReplyDTOList.stream().map(EvaluateReplyDTO::getCreatedBy).collect(Collectors.toList()));
        // 填充昵称
        Map<Long, String> userNickNameMap = userCacheService.getMultiUserNickName(evaluateReplyDTOList.stream().map(EvaluateReplyDTO::getCreatedBy).collect(Collectors.toList()));
        evaluateReplyDTOList.forEach(item -> {
            item.setAvatar(MapUtils.getString(userAvatarMap, item.getCreatedBy(), ""));
            item.setNickName(MapUtils.getString(userNickNameMap, item.getCreatedBy(), ""));
        });

        /**
         * 1、填充每条跟评对应的点赞数量
         */
        buildLikesData(evaluateReplyDTOList);
        /**
         * 2、填充评价对应的附件
         */
        if (Objects.nonNull(req.getEvaluateId())) {
            Set<Long> evaluateReplyIdSet = evaluateReplyDTOList.stream().map(EvaluateReplyDTO::getEvaluateReplyId).collect(Collectors.toSet());
            // 2、填充评价对应的附件 (个人中心-点赞-回复-不需要展示回复图片)
            if (CollUtil.isNotEmpty(evaluateReplyIdSet)) {
                Map<Long, List<AttachmentResp>> attachmentMap = attachmentService.getAttachmentByIds(new ArrayList<>(evaluateReplyIdSet));
                evaluateReplyDTOList.forEach(item -> item.setAttachmentList(attachmentMap.get(item.getEvaluateReplyId())));
            }
        }
        /**
         * 3、填充评价对应的附件
         */
        if (Objects.nonNull(req.getUserId())) {
            processByUserId(evaluateReplyDTOList);
        }
        return evaluateDTOIPage;
    }

    /**
     * 构建评价的点赞统计及个人点赞数据
     *
     * @param result
     */
    private void buildLikesData(List<EvaluateReplyDTO> result) {
        if (CollUtil.isEmpty(result)) {
            return;
        }
        // 填充每条跟评对应的点赞数量
        Optional.of(result).ifPresent(list -> {
            List<ObjectCount> objectCountList = myStatisticsService.countByObjectIds(list.stream().map(EvaluateReplyDTO::getEvaluateReplyId).collect(Collectors.toList()));
            Optional.ofNullable(objectCountList).ifPresent(list1 -> list1.forEach(item -> {
                EvaluateReplyDTO replyDTO = result.stream().filter(replyItem -> replyItem.getEvaluateReplyId().equals(item.getObjectId())).findFirst().orElse(null);
                if (Objects.nonNull(replyDTO) && MyStatisticsTypeEnum.LIKES_EVALUATE_REPLY_NUM.getBusinessType().equals(item.getBusinessType())) {
                    replyDTO.setLikesCount(item.getObjectCount());
                }
            }));
        });
        // 是否有我的点赞
        result.forEach(evaluateDTO -> {
            if (Objects.nonNull(evaluateDTO.getLikesCount()) && evaluateDTO.getLikesCount() > 0) {
                evaluateDTO.setHasOwnerLikes(userActionCacheService.getOwnerAction(SecurityUtils.getUserId(), evaluateDTO.getEvaluateReplyId(),
                        MyStatisticsTypeEnum.LIKES_EVALUATE_REPLY_NUM.getBusinessType()));
            }
        });
    }

    private void processByUserId(List<EvaluateReplyDTO> evaluateReplyDTOList) {
        Set<Long> evaluateIdSet = evaluateReplyDTOList.stream().map(EvaluateReplyDTO::getEvaluateId).collect(Collectors.toSet());
        // 1、查询评价
        List<BrandTasteEvaluate> brandTasteEvaluateList = evaluateService.list(new LambdaQueryWrapper<BrandTasteEvaluate>()
                .in(BrandTasteEvaluate::getEvaluateId, evaluateIdSet)
                .eq(BrandTasteEvaluate::getDeletedVersion, 0L)
                .orderByDesc(BrandTasteEvaluate::getCreatedTime)
        );
        List<BrandTasteEvaluateDTO> brandTasteEvaluateDTOList = BrandTasteEvaluateMapping.INSTANCE.coverToDTOList(brandTasteEvaluateList);
        if (CollUtil.isEmpty(brandTasteEvaluateDTOList)) {
            return;
        }
        // 2、填充评价对应的附件
        if (CollUtil.isNotEmpty(brandTasteEvaluateDTOList)) {
            Map<Long, String> userNickNameMap = userCacheService.getMultiUserNickName(brandTasteEvaluateDTOList.stream().map(BrandTasteEvaluateDTO::getCreatedBy).collect(Collectors.toList()));
            Map<Long, List<AttachmentResp>> attachmentMap = attachmentService.getAttachmentByIds(new ArrayList<>(evaluateIdSet));
            brandTasteEvaluateDTOList.forEach(item -> {
                item.setAttachmentList(attachmentMap.get(item.getEvaluateId()));
                // 设置昵称
                item.setNickName(MapUtils.getString(userNickNameMap, item.getCreatedBy(), ""));
            });
        }
        // 3、填充评价到回复DTO中
        evaluateReplyDTOList.forEach(item -> item.setEvaluate(
                brandTasteEvaluateDTOList.stream()
                        .filter(brandTasteEvaluateDTO -> brandTasteEvaluateDTO.getEvaluateId().equals(item.getEvaluateId())).findFirst().orElse(null)));
    }

}
